package cn.community.system.shiro;

import cn.community.system.domain.Association;
import cn.community.system.mapper.PermissionMapper;
import cn.community.system.mapper.RoleMapper;
import cn.community.system.service.IAssociationService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component("associationRealm")
public class AssociationRealm extends AuthorizingRealm{

    @Autowired
    private IAssociationService associationService;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    //从spring容器中找到credentialsMatcher ,注入进去
    @Autowired
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        super.setCredentialsMatcher(credentialsMatcher);
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("AssociationRealm 执行授权逻辑");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登录用户
        Subject subject = SecurityUtils.getSubject();
        Association association = (Association)subject.getPrincipal();
        // 加入角色和权限
        info.addRole("association");
        Long id = roleMapper.findlIdByRoleName("association");
        List<String> permissions = permissionMapper.selectByRoleId(id);
        info.addStringPermissions(permissions);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("AssociationRealm 执行认证逻辑");
        Association association = null;
        // 1. 把AuthenticationToken转换为CustomizedToken
        UserToken userToken = (UserToken) token;
        // 2. 从CustomizedToken中获取username
        String username = userToken.getUsername();
        // 3. 若用户不存在，抛出UnknownAccountException异常
        association = associationService.getAssociationByUsername(username);
        if (association == null)
            throw new UnknownAccountException("用户不存在！");
        if (association.getIsAgree() != 1)
            throw new UnknownAccountException("用户不存在！");
        // 4.
        // 根据用户的情况，来构建AuthenticationInfo对象并返回，通常使用的实现类为SimpleAuthenticationInfo
        // 以下信息从数据库中获取
        // （1）principal：认证的实体信息，可以是username，也可以是数据表对应的用户的实体类对象
        Object principal = association;
        // （2）credentials：密码
        Object credentials = association.getPassword();
        // （3）realmName：当前realm对象的name，调用父类的getName()方法即可
        String realmName = getName();
        // （4）盐值：取用户信息中唯一的字段来生成盐值，避免由于两个用户原始密码相同，加密后的密码也相同
        ByteSource credentialsSalt = ByteSource.Util.bytes(username);
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt,
                realmName);
        System.out.println("已经设置当前登录对象");
        return info;
    }
}
